﻿using Blog.Common.Helper;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Text;

namespace Blog.Common.Redis
{
    public class RedisCacheManager : IRedisCacheManager
    {
        private readonly string _redisConnectionString;
        private volatile ConnectionMultiplexer _redisConnection;
        private readonly object _redisConnectionLock = new object();
        public RedisCacheManager()
        {
            string redisConfiguration = Appsettings.app(new string[] { "AppSettings", "RedisCachingAOP", "ConnectionString" });//获取连接字符串
            if (string.IsNullOrEmpty(redisConfiguration))
            {
                throw new ArgumentException("redis config is empty", nameof(redisConfiguration));
            }
            _redisConnectionString = redisConfiguration;
            _redisConnection = GetRedisConnection();
        }

        /// <summary>
        /// 单例模式，获取Redis连接
        /// </summary>
        /// <returns></returns>
        private ConnectionMultiplexer GetRedisConnection()
        {
            //如果已经连接实例，直接返回
            if (_redisConnection != null && _redisConnection.IsConnected)
            {
                return _redisConnection;
            }
            //加锁，防止异步编程中，出现单例无效的问题
            lock (_redisConnectionLock)
            {
                if (_redisConnection != null)
                {
                    //释放redis连接
                    _redisConnection.Dispose();
                }
                try
                {
                    _redisConnection = ConnectionMultiplexer.Connect(_redisConnectionString);
                }
                catch (Exception)
                {

                    throw new Exception("Redis服务未开启，请检查");
                }
            }
            return _redisConnection;
        }

        public void Clear()
        {
            foreach (var endPoint in GetRedisConnection().GetEndPoints())
            {
                var server = GetRedisConnection().GetServer(endPoint);
                foreach (var key in server.Keys())
                {
                    _redisConnection.GetDatabase().KeyDelete(key);
                }
            }
        }

        public TEntity Get<TEntity>(string key)
        {
            var value = _redisConnection.GetDatabase().StringGet(key);
            if (value.HasValue)
            {
                return SerializeHelper.Deserialize<TEntity>(value);
            }
            return default(TEntity);
        }

        public string GetValue(string key)
        {
            return _redisConnection.GetDatabase().StringGet(key);
        }

        public bool IsExists(string key)
        {
            return _redisConnection.GetDatabase().KeyExists(key);
        }

        public void Remove(string key)
        {
            _redisConnection.GetDatabase().KeyDelete(key);
        }

        public void Set(string key, object value, TimeSpan cacheTime)
        {
            if (value != null)
            {
                _redisConnection.GetDatabase().StringSet(key, SerializeHelper.Serialize(value), cacheTime);
            }
        }

        public void SetValue(string key, byte[] value)
        {
            if (value.Length>0)
            {
                _redisConnection.GetDatabase().StringSet(key, value, TimeSpan.FromSeconds(120));
            }
        }
    }
}
